package com.gopay.bis.kuaiqian.ebank.operation;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.kuaiqian.ebank.KuaiQianMessage;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.ICertHelper;

@Service("kuaiQianCertHelper")
public class KuaiQianCertHelper implements ICertHelper {

	@Value("${cert.kuaiqian.privatekey}")
	private String privateKeyPath;
	@Value("${cert.kuaiqian.publickey}")
	private String publicKeyPath;
	@Value("${cert.kuaiqian.pwd}")
	private String keyPwd;
	
	@SuppressWarnings("restriction")
	public String sign(BaseMessage bsaeMessage) throws GopayException {
		 KuaiQianMessage kqMessage = (KuaiQianMessage)bsaeMessage;
		  String plain = kqMessage.getPlainMessage();
		  BankLogUtils.printB2CSignPlainLog(kqMessage);
	        String base64 = "";
	        FileInputStream ksfis=null;
	        BufferedInputStream ksbufin =null;
	        try {
	            // 密钥仓库
	            KeyStore ks = KeyStore.getInstance("PKCS12");

	            // 读取密钥仓库
	            ksfis = new FileInputStream(privateKeyPath);
	            ksbufin = new BufferedInputStream(ksfis);

	            char[] keyPwdChar = keyPwd.toCharArray();
	            ks.load(ksbufin, keyPwdChar);
	            // 从密钥仓库得到私钥
	            PrivateKey priK = (PrivateKey) ks.getKey("test-alias", keyPwdChar);
	            Signature signature = Signature.getInstance("SHA1withRSA");
	            signature.initSign(priK);
	            signature.update(plain.getBytes("utf-8"));
	            sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
	            base64 = encoder.encode(signature.sign());
	            BankLogUtils.printB2CSignSignatureLog(kqMessage, base64);
	           
	            //logger.error("sign result :" + base64);
	        } catch (FileNotFoundException e) {
	           // logger.error("找不到证书文件");
	        	BankLogUtils.printB2CSignExceptionLog(bsaeMessage, e);
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
	        } catch (Exception ex) {
	        	BankLogUtils.printB2CSignExceptionLog(bsaeMessage, ex);
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
	        }finally{
	        	try {
	        		if (null != ksbufin) {
						ksbufin.close();
					}
					if (null != ksfis) {
						ksfis.close();
					}
				} catch (IOException e) {
				}
	        }
	        return base64;

	}

	@SuppressWarnings("restriction")
	public Object verify(BaseMessage bsaeMessage) throws GopayException {
		  boolean flag = false;
		  InputStream inStream =null;
	        try {
	            // 获得文件(绝对路径)
	            inStream = new FileInputStream(publicKeyPath);

	            CertificateFactory cf = CertificateFactory.getInstance("X.509");
	            X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
	            // 获得公钥
	            PublicKey pk = cert.getPublicKey();
	            // 签名
	            Signature signature = Signature.getInstance("SHA1withRSA");
	            signature.initVerify(pk);
	            signature.update((bsaeMessage.getPlainMessage()).getBytes());
	            // 解码
	            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
	            BankLogUtils.printB2CVerifyPlainLog(bsaeMessage);			
	            flag = signature.verify(decoder.decodeBuffer((bsaeMessage.getSignMessage())));
	            BankLogUtils.printB2CVerifyResultLog(bsaeMessage, flag);
	        } catch (Exception e) {
	        	BankLogUtils.printB2CVerifyExceptionLog(bsaeMessage, e);
	        }finally{
	        	try {
	        		if (null != inStream) {
						inStream.close();
					}
				} catch (IOException e) {
				}
	        }
	        return flag;
	}

}
